package service

import (
	"context"

	"gitee.com/night-tc/gobige/entity"
	"gitee.com/night-tc/gobige/global"
	"gitee.com/night-tc/gobige/logger"
	"gitee.com/night-tc/gobige/msgdef"
	"gitee.com/night-tc/gobige/msgdef/protomsg"
	"gitee.com/night-tc/gobige/msghandler"
	"gitee.com/night-tc/gobige/sess"
)

/*
服务器级的消息处理
*/

type Service_Proc struct {
	*Service
}

// 处理连接被关的时候的消息,一般只需要输出信息就好
func (this *Service_Proc) MsgProc_SessClosed(msg *protomsg.SessClosed) {
	logger.Infof("SessClosed sid:%d;", msg.GetSessUID())
	this.CallDelay(func() {
		this.real.OnServerSessDisconnect(msg.SessUID)
	})
}

// 处理转发过来的信息
func (this *Service_Proc) MsgProc_ForwardMsgSrv(msg *protomsg.ForwardMsgSrv) {
	// if msg.SrvID != this.Sinfo.ServerID {
	// 	this.PostSess(msg.SrvID, msg)
	// 	return
	// }
	if msg.SrvType == global.ServerTypeClient {
		/*
			如果是给客户端的，那就拿 到对象直接Post数据流
			因为流是处理过的
		*/
		if e := this.GetEntity(msg.EntityID); e == nil {
			logger.Warnf("Entity %d not exist.", msg.EntityID)
			return
		} else if real, ok := e.(entity.IPost); ok {
			err := real.PostBuf(msg.MsgContent)
			if err != nil {
				logger.Warnf("PostBuf Entity %d Error:%v.", msg.EntityID, err)
			}
			return
		} else {
			logger.Warnf("Entity %d not IClientSess.", msg.EntityID)
			return
		}
	} else {
		msgh := this.getHandler(msg.SpaceID, msg.EntityID)
		if msgh == nil {
			return
		}
		if fmsg, err := sess.DecodeMsg(msg.MsgContent[3], msg.MsgContent[4:]); err != nil {
			logger.Warnf("MsgProc_ForwardMsgSrv:%v", err)
		} else {
			msgh.FireMsg(fmsg.Name(), fmsg)
		}
	}

}

// 处理转发过来的RPC
func (this *Service_Proc) MsgProc_ForwardRPCSrv(msg *protomsg.ForwardRPCSrv) {
	// if msg.SrvID != this.Sinfo.ServerID {
	// 	this.PostSess(msg.SrvID, msg)
	// 	return
	// }
	msgh := this.getHandler(msg.SpaceID, msg.EntityID)
	if msgh == nil {
		return
	}
	if fmsg, err := sess.DecodeMsgByMsgID(0, msg.MsgContent, msg.MsgID); err != nil {
		logger.Error("MsgProc_ForwardRPCSrv:", err)
	} else {
		msgh.FireRPC(msg.RPCName, fmsg)
	}
}

// 处理其他服务器要发给客户的消息
func (this *Service_Proc) MsgProc_EntityMsgRet(msg *protomsg.EntityMsgRet) {
	//一般发给客户

}

func (this *Service_Proc) getHandler(spid, eid uint64) (result msghandler.IMsgHandler) {
	if spid == 0 && eid == 0 {
		return this.Service
	} else if spid != 0 {
		//有场景
		if e := this.Entities.GetEntity(spid); e == nil {
			return nil
		} else if eid == 0 {
			//发给场景的
			return e
		} else if es, ok := e.(entity.IEntities); ok {
			if e = es.GetEntity(eid); e != nil {
				return e
			}
		}
	} else if e := this.GetEntity(eid); e != nil {
		//spid==0 && eid!=0
		return e
	}
	return nil

}

// 处理转发过来需要回包的服务器消息
func (this *Service_Proc) MsgProc_RouteMsgSrvReq(msg *protomsg.RouteMsgSrvReq) {
	// 处理路由消息请求
	logger.Infof("RouteMsgSrvReq received for EntityID: %d", msg.EntityID)
	innermsg, err := msgdef.GetTypeMgr().NewMsgByName(msg.MsgName, msg.MsgData)
	if err != nil {
		logger.Error("消息解析错误: ", err)
		return
	}
	msgh := this.getHandler(0, 0)
	if msg.PID == 0 {
		// 表示服务器消息
		msgh.FireSrv(msg.MsgName, msg, innermsg)
		// msgh.DoSrvMsg(msg.MsgName, msg, innermsg)
		return
	} else if msg.EntityID != 0 {
		//有玩家协程
		msgh = this.getHandler(msg.SpaceID, msg.EntityID)
		// msgh = this.GetEntityByDBID(msg.PID, entity.Entity_Type_Player)
		if msgh != nil {
			msgh.FireSrv(msg.MsgName, msg, innermsg)
			return
		}
	} else {
		// 需要独立协程处理
		this.thgo.Go(func(ctx context.Context) {
			msgh.DoSrvMsg(msg.MsgName, msg, innermsg)
		})
		return
	}
	logger.Warnf("RouteMsgSrvReq EntityID:%d PID:%d MsgName:%s not found", msg.EntityID, msg.PID, msg.MsgName)
	// 没找到对象，可能是因为玩家已经下线，需要直接返回
	this.Service.OnSrvReturn(msg, innermsg, entity.ErrNtt_EID_Not_Exist.NewErr(nil, msg.EntityID))

}

// 处理转发过来的服务器消息返回
func (this *Service_Proc) MsgProc_RouteMsgSrvRet(msg *protomsg.RouteMsgSrvRet) {
	data, loaded := this.WaitList.LoadAndDelete(msg.BackKey)
	if !loaded {
		logger.Warnf("No data found for BackKey: %v", msg.BackKey)
		return
	}
	ch := data.(chan *protomsg.RouteMsgSrvRet)
	select {
	case ch <- msg:
	default:
		logger.Warnf("Channel is full for BackKey: %v", msg.BackKey)
	}
}

// 设置服务器状态
func (this *Service_Proc) MsgProc_SetServerStatusReq(msg *protomsg.SetServerStatusReq) {
	this.Status.Store(int32(msg.ServerStatus))
	logger.Infof("Server status updated to: %d", msg.ServerStatus)
	this.Service.DisMgr.UpStatus(int32(msg.ServerStatus))
}
